package com.ikingtech.platform.service.system.user.service;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.department.api.DeptUserApi;
import com.ikingtech.framework.sdk.department.model.DeptManagerDTO;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.platform.service.system.user.entity.UserDO;
import com.ikingtech.platform.service.system.user.entity.UserDeptDO;
import com.ikingtech.platform.service.system.user.service.repository.UserDeptRepository;
import com.ikingtech.platform.service.system.user.service.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author tie yan
 */
@RequiredArgsConstructor
public class DeptUserService implements DeptUserApi {

    private final UserRepository repo;

    private final UserDeptRepository userDeptRepo;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void moveUser(String parentId, List<String> deptIds) {
        if (Tools.Coll.isBlank(deptIds)) {
            return;
        }
        List<String> userIds = this.userDeptRepo.listObjs(Wrappers.<UserDeptDO>lambdaQuery()
                .select(UserDeptDO::getUserId)
                .in(UserDeptDO::getDeptId, deptIds)
                .eq(UserDeptDO::getTenantCode, Me.tenantCode()), String.class::cast);
        if (Tools.Coll.isBlank(userIds)) {
            return;
        }
        List<String> existUserIds = this.userDeptRepo.listObjs(Wrappers.<UserDeptDO>lambdaQuery()
                .select(UserDeptDO::getUserId)
                .eq(UserDeptDO::getDeptId, parentId), String.class::cast);
        this.userDeptRepo.saveBatch(Tools.Coll.convertList(userIds, userId -> Tools.Coll.isBlank(existUserIds) || !existUserIds.contains(userId), id -> {
            UserDeptDO entity = new UserDeptDO();
            entity.setId(Tools.Id.uuid());
            entity.setUserId(id);
            entity.setDeptId(parentId);
            return entity;
        }));

        this.userDeptRepo.remove(Wrappers.<UserDeptDO>lambdaQuery().in(UserDeptDO::getDeptId, deptIds));
    }

    @Override
    public DeptManagerDTO loadManager(String userId) {
        UserDO entity = this.repo.getById(userId);
        if (null == entity) {
            return null;
        }
        DeptManagerDTO manager = new DeptManagerDTO();
        manager.setUserId(entity.getId());
        manager.setUserName(entity.getName());
        manager.setUserAvatar(entity.getAvatar());
        return manager;
    }

    @Override
    public List<DeptManagerDTO> loadManagers(List<String> userIds) {
        if (Tools.Coll.isBlank(userIds)) {
            return new ArrayList<>();
        }
        List<UserDO> entities = this.repo.listByIds(userIds);
        if (Tools.Coll.isBlank(entities)) {
            return new ArrayList<>();
        }
        return Tools.Coll.convertList(entities, entity -> {
            DeptManagerDTO manager = new DeptManagerDTO();
            manager.setUserId(entity.getId());
            manager.setUserName(entity.getName());
            manager.setUserAvatar(entity.getAvatar());
            return manager;
        });
    }

    @Override
    public Map<String, Integer> getUserCount(List<String> deptIds) {
        if (Tools.Coll.isBlank(deptIds)) {
            return new HashMap<>();
        }
        List<UserDeptDO> userDeptEntities = this.userDeptRepo.list(Wrappers.<UserDeptDO>lambdaQuery().in(UserDeptDO::getDeptId, deptIds));
        Map<String, List<UserDeptDO>> userDeptMap = Tools.Coll.convertGroup(userDeptEntities, UserDeptDO::getDeptId);

        Map<String, Integer> result = new HashMap<>(userDeptMap.size());
        userDeptMap.forEach((deptId, entities) -> result.put(deptId, entities.size()));
        return result;
    }
}
